/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package edu.lnu.ums.dal.factories;

import edu.lnu.ums.dal.exception.EntityManagerFactoryCreationException;
import edu.lnu.ums.entities.Charity;
import edu.lnu.ums.entities.Expenditures;
import edu.lnu.ums.entities.core.AbstractEntity;
import edu.lnu.ums.entities.core.AbstractProcess;
import edu.lnu.ums.entities.dictionaries.Country;
import edu.lnu.ums.entities.dictionaries.Months;
import edu.lnu.ums.entities.dictionaries.Sex;
import edu.lnu.ums.entities.dictionaries.Subject;
import edu.lnu.ums.entities.dictionaries.UMSType;
import edu.lnu.ums.entities.processes.Amortization;
import edu.lnu.ums.entities.processes.CharityProcess;
import edu.lnu.ums.entities.processes.ComputerAmortization;
import edu.lnu.ums.entities.processes.CourseWork;
import edu.lnu.ums.entities.processes.ElectricAmortization;
import edu.lnu.ums.entities.processes.ExpendituresProcess;
import edu.lnu.ums.entities.processes.PhDWork;
import edu.lnu.ums.entities.processes.PostgraduateWork;
import edu.lnu.ums.entities.processes.ProfGrowth;
import edu.lnu.ums.entities.processes.SalaryProcess;
import edu.lnu.ums.entities.processes.ScientificWork;
import edu.lnu.ums.entities.processes.StudyGrowth;
import edu.lnu.ums.entities.security.User;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import org.firebirdsql.pool.FBSimpleDataSource;
import org.hibernate.ejb.Ejb3Configuration;
import net.sourceforge.jtds.jdbcx.JtdsDataSource;



public class FactoriesCache {
    public static final String DEFAULT_FACTORY_NAME = "default";
    
    private static FactoriesCache cache;

    private Map<String, EntityManagerFactory> factories;

    private FactoriesCache() {
        factories = new HashMap<String, EntityManagerFactory>();
    }

    public EntityManagerFactory getDefaultFactory() {
        return factories.get(DEFAULT_FACTORY_NAME);
    }

    public String getNameByEntityManagerFactory(EntityManagerFactory factory) {
        for (Entry<String, EntityManagerFactory> entry : factories.entrySet()) {
            if (entry.getValue() == factory) {
                return entry.getKey();
            }
        }

        return "";
    }

    public static FactoriesCache getInstance() {
        if (cache == null) {
            cache = new FactoriesCache();
        }

        return cache;
    }

    public EntityManagerFactory getFactory(String name) {
        return factories.get(name);
    }

    public EntityManagerFactory addFactory(String name, String pathToDb, String user, String password, String provider) throws EntityManagerFactoryCreationException {
        EntityManagerFactory factory = configureFactory(pathToDb, user, password, provider);
        factories.put(name, factory);

        return factory;
    }

    public void removeFactory(String name) {
        EntityManagerFactory factory = getFactory(name);
        if (factory != null) {
            factory.close();
            factories.remove(name);
        }
    }

    private EntityManagerFactory configureFactory(String pathToDb, String user, String password, String provider) throws EntityManagerFactoryCreationException {
         Ejb3Configuration ejbconf = new Ejb3Configuration();
        if(provider.equals("Firebird")){
           FBSimpleDataSource ds = new FBSimpleDataSource();
           ds.setDatabase(pathToDb);
           ds.setUserName(user);
           ds.setPassword(password);

           ejbconf.setDataSource(ds);
           ejbconf.setProperty("hibernate.dialect", "org.hibernate.dialect.FirebirdDialect");
           ejbconf.setProperty("hibernate.show_sql", "false");
           ejbconf.setProperty("hibernate.hbm2ddl.auto", "update");
        }
        else{
            JtdsDataSource ds=new JtdsDataSource();
            String[] strs=pathToDb.split(" ");
            if(strs.length==4){
                  ds.setServerName(strs[0]);
                  ds.setInstance(strs[1]);
                  ds.setPortNumber(Integer.parseInt(strs[2]));
                  ds.setDatabaseName(strs[3]);
            }
            else{
                 ds.setServerName(strs[0]);
                 ds.setPortNumber(Integer.parseInt(strs[1]));
                 ds.setDatabaseName(strs[2]);
            }
            ds.setUser(user);
            ds.setPassword(password);
            ds.setCharset("UTF-8");

           
            ejbconf.setDataSource(ds);
            ejbconf.setProperty("hibernate.dialect", "org.hibernate.dialect.SQLServerDialect");
            ejbconf.setProperty("hibernate.show_sql", "false");
            ejbconf.setProperty("hibernate.hbm2ddl.auto", "update");
        }
            EntityManagerFactory emf = configureCommonProperties(ejbconf);
            return emf;
           
    }

    private EntityManagerFactory configureCommonProperties(Ejb3Configuration ejbconf) throws EntityManagerFactoryCreationException{
        try{
        //core
            ejbconf.addAnnotatedClass(AbstractEntity.class);
            ejbconf.addAnnotatedClass(AbstractProcess.class);

            // dictionraries
            ejbconf.addAnnotatedClass(Country.class);
            ejbconf.addAnnotatedClass(Sex.class);
            ejbconf.addAnnotatedClass(Subject.class);
            ejbconf.addAnnotatedClass(UMSType.class);
            ejbconf.addAnnotatedClass(Months.class);

            // security
            ejbconf.addAnnotatedClass(User.class);

            // processes
            ejbconf.addAnnotatedClass(Amortization.class);
            ejbconf.addAnnotatedClass(ComputerAmortization.class);
            ejbconf.addAnnotatedClass(ElectricAmortization.class);
            ejbconf.addAnnotatedClass(ScientificWork.class);
            ejbconf.addAnnotatedClass(ExpendituresProcess.class);
            ejbconf.addAnnotatedClass(CharityProcess.class);
            ejbconf.addAnnotatedClass(SalaryProcess.class);
            ejbconf.addAnnotatedClass(CourseWork.class);
            ejbconf.addAnnotatedClass(PostgraduateWork.class);
            ejbconf.addAnnotatedClass(PhDWork.class);
            ejbconf.addAnnotatedClass(ProfGrowth.class);
            ejbconf.addAnnotatedClass(StudyGrowth.class);
     
       
            ejbconf.addAnnotatedClass(Expenditures.class);
            ejbconf.addAnnotatedClass(Charity.class);

            for (UMSType type : UMSType.getUMSTypes()) {
                try {
                    ejbconf.addAnnotatedClass(Class.forName(type.getJavaClassName()));
                } catch (ClassNotFoundException ex) {
                    ex.printStackTrace();
                }
            }


            ejbconf.buildMappings();
            EntityManagerFactory emf = ejbconf.buildEntityManagerFactory();
            EntityManager em = emf.createEntityManager();
            em.createNativeQuery("select 1 from umsobject").getResultList();
            em.close();

            return emf;

        } catch (Exception ex) {
            throw new EntityManagerFactoryCreationException(ex);
        }
    }
}
